feat(headless): remove data-cl-slot, de-prefix state data attributes#9237
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 2acb5df The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/electron
@clerk/electron-passkeys
@clerk/eslint-plugin
@clerk/expo
@clerk/expo-google-signin
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
📝 WalkthroughWalkthroughThe headless primitives now emit generic Estimated code review effort: 4 (Complex) | ~60 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Warning Review ran into problems🔥 ProblemsLinked repositories: Couldn't analyze
Errors logged to '/home/jailuser/git/.git/lfs/logs/20260724T002932.877485564.log'. Errors logged to '/home/jailuser/git/.git/lfs/logs/20260724T003053.699745391.log'. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (2)
packages/headless/src/primitives/tooltip/tooltip.test.tsx (1)
34-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse Testing Library queries for the new test IDs.
Replace
document.querySelector(...)withscreen.getByTestId(...)for required elements andscreen.queryByTestId(...)for absence checks. This keeps the tests aligned with React Testing Library and improves failure diagnostics.As per coding guidelines, React component tests must use proper React Testing Library queries.
Also applies to: 44-44, 60-60, 89-89, 98-98, 111-111, 134-136, 157-157, 170-170, 179-179, 189-189, 198-198, 205-205
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/headless/src/primitives/tooltip/tooltip.test.tsx` at line 34, Replace document.querySelector checks in the tooltip tests with React Testing Library screen queries: use screen.getByTestId for required tooltip elements and screen.queryByTestId for absence checks. Update all referenced assertions while preserving their existing expected outcomes.Source: Coding guidelines
packages/headless/src/primitives/tabs/tabs.test.tsx (1)
29-30: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winKeep a regression test for slot removal.
After removing these assertions, the suite no longer verifies that Tabs parts do not emit the deprecated
data-cl-slotattribute. Add one focused absence assertion covering the tablist, tabs, panels, and indicator so this contract cannot silently regress.Also applies to: 368-368
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/headless/src/primitives/tabs/tabs.test.tsx` around lines 29 - 30, Add a focused regression test within the Tabs “ARIA attributes” suite that asserts the tablist, tabs, panels, and indicator do not emit the deprecated data-cl-slot attribute. Use the existing Tabs test setup and absence-assertion style, preserving the current ARIA behavior checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/headless/src/primitives/accordion/accordion-root.tsx`:
- Around line 60-66: Update the Home/End handling in the accordion root’s
onKeyDown handler to collect only this Accordion’s registered or uniquely
identified enabled triggers, excluding elements with aria-disabled="true". Do
not use the broad subtree selector that can include nested accordions or
unrelated aria-expanded controls, and preserve the existing Home/End navigation
behavior for the filtered trigger list.
In `@packages/headless/src/primitives/collapsible/collapsible.test.tsx`:
- Line 31: Extend the collapsible tests around the root, trigger, and panel
assertions to verify removed legacy attributes are absent: data-cl-slot,
data-cl-open, data-cl-closed, and data-cl-disabled. Add negative assertions at
the referenced test cases while preserving the existing positive checks for the
new attributes.
In `@packages/headless/src/primitives/collapsible/README.md`:
- Around line 94-100: Update the collapsible usage example to apply
className="cl-collapsible-panel" to the panel element targeted by the CSS
selector, ensuring the documented example works with the provided animation
styles.
In `@packages/headless/src/primitives/file-upload/file-upload.test.tsx`:
- Around line 303-307: Extend the file-upload tests around the disabled trigger
case and the additional referenced case to assert that legacy data-cl-slot and
data-cl-disabled attributes are absent. Check the hidden input plus the root,
dropzone, and trigger elements, while preserving the existing positive
assertions for the replacement attributes and selectors.
In `@packages/headless/src/primitives/popover/popover-arrow.tsx`:
- Around line 19-20: The computed data-side attribute must take precedence over
consumer props in both arrow components. In
packages/headless/src/primitives/popover/popover-arrow.tsx lines 19-20, move
data-side after the props spread; apply the same ordering change in
packages/headless/src/primitives/select/select-arrow.tsx lines 16-17, preserving
the computed side for styling.
In `@packages/headless/src/primitives/tooltip/tooltip-positioner.tsx`:
- Line 20: The computed data-side value must remain authoritative in both
tooltip surfaces. Update TooltipPositioner in
packages/headless/src/primitives/tooltip/tooltip-positioner.tsx:20 so mergeProps
does not allow otherProps to override data-side, and update TooltipArrow in
packages/headless/src/primitives/tooltip/tooltip-arrow.tsx:19 so the computed
side is assigned after consumer props; preserve all other prop-merging behavior.
In `@packages/swingset/src/stories/accordion.mdx`:
- Around line 114-119: Update the Accordion.Panel usage in
packages/swingset/src/stories/accordion.mdx (lines 114-119) to pass the
cl-accordion-panel class, and update the Tabs.Indicator usage in
packages/swingset/src/stories/tabs.mdx (line 122) to pass the cl-tabs-indicator
class; keep each example’s CSS selector consistent with the class assigned to
its primitive.
In `@packages/swingset/src/stories/autocomplete.stories.tsx`:
- Line 10: The story descriptions incorrectly characterize data-* attributes as
ARIA wiring. Update the wording in the component story descriptions for
Autocomplete, Collapsible, Popover, and Select to describe data-* attributes as
emitted state or styling selectors, while identifying roles and aria-*
attributes as the accessibility wiring; apply this at
packages/swingset/src/stories/autocomplete.stories.tsx:10-10,
packages/swingset/src/stories/collapsible.stories.tsx:7-7,
packages/swingset/src/stories/popover.stories.tsx:7-7, and
packages/swingset/src/stories/select.stories.tsx:7-7.
In `@packages/swingset/src/stories/collapsible.mdx`:
- Around line 80-90: Update the examples so their CSS selectors match the
rendered headless parts: in packages/swingset/src/stories/collapsible.mdx lines
80-90, assign className='cl-collapsible-panel' to Collapsible.Panel; in
packages/swingset/src/stories/popover.mdx lines 121-127, assign
className='cl-popover-popup' to Popover.Popup. Ensure both samples visibly
demonstrate the required class assignments.
In `@packages/swingset/src/stories/dialog.stories.tsx`:
- Line 7: Reword the comments at
packages/swingset/src/stories/dialog.stories.tsx#L7-L7 to state that the
primitive provides ARIA wiring and emits data-* attributes for styling; at
packages/swingset/src/stories/drawer.stories.tsx#L7-L7, distinguish ARIA wiring
from gesture/state data-* hooks; and at
packages/swingset/src/stories/menu.stories.tsx#L7-L7, distinguish ARIA wiring
from positioning/state data-* hooks. No implementation changes are needed.
---
Nitpick comments:
In `@packages/headless/src/primitives/tabs/tabs.test.tsx`:
- Around line 29-30: Add a focused regression test within the Tabs “ARIA
attributes” suite that asserts the tablist, tabs, panels, and indicator do not
emit the deprecated data-cl-slot attribute. Use the existing Tabs test setup and
absence-assertion style, preserving the current ARIA behavior checks.
In `@packages/headless/src/primitives/tooltip/tooltip.test.tsx`:
- Line 34: Replace document.querySelector checks in the tooltip tests with React
Testing Library screen queries: use screen.getByTestId for required tooltip
elements and screen.queryByTestId for absence checks. Update all referenced
assertions while preserving their existing expected outcomes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 420617cc-13ad-47f3-8283-80d1117b0bdc
📒 Files selected for processing (120)
.changeset/headless-remove-data-cl-slot.mdpackages/headless/README.mdpackages/headless/src/hooks/use-animations-finished.test.tspackages/headless/src/hooks/use-animations-finished.tspackages/headless/src/hooks/use-transition.test.tspackages/headless/src/hooks/use-transition.tspackages/headless/src/primitives/accordion/README.mdpackages/headless/src/primitives/accordion/accordion-header.tsxpackages/headless/src/primitives/accordion/accordion-item.tsxpackages/headless/src/primitives/accordion/accordion-panel.tsxpackages/headless/src/primitives/accordion/accordion-root.tsxpackages/headless/src/primitives/accordion/accordion-trigger.tsxpackages/headless/src/primitives/accordion/accordion.test.tsxpackages/headless/src/primitives/autocomplete/README.mdpackages/headless/src/primitives/autocomplete/autocomplete-arrow.tsxpackages/headless/src/primitives/autocomplete/autocomplete-input.tsxpackages/headless/src/primitives/autocomplete/autocomplete-list.tsxpackages/headless/src/primitives/autocomplete/autocomplete-option.tsxpackages/headless/src/primitives/autocomplete/autocomplete-popup.tsxpackages/headless/src/primitives/autocomplete/autocomplete-positioner.tsxpackages/headless/src/primitives/autocomplete/autocomplete-root.tsxpackages/headless/src/primitives/autocomplete/autocomplete.test.tsxpackages/headless/src/primitives/collapsible/README.mdpackages/headless/src/primitives/collapsible/collapsible-panel.tsxpackages/headless/src/primitives/collapsible/collapsible-root.tsxpackages/headless/src/primitives/collapsible/collapsible-trigger.tsxpackages/headless/src/primitives/collapsible/collapsible.test.tsxpackages/headless/src/primitives/dialog/README.mdpackages/headless/src/primitives/dialog/dialog-backdrop.tsxpackages/headless/src/primitives/dialog/dialog-trigger.tsxpackages/headless/src/primitives/dialog/dialog-viewport.tsxpackages/headless/src/primitives/dialog/dialog.test.tsxpackages/headless/src/primitives/drawer/README.mdpackages/headless/src/primitives/drawer/css-vars.tspackages/headless/src/primitives/drawer/drawer-backdrop.tsxpackages/headless/src/primitives/drawer/drawer-handle-grip.tsxpackages/headless/src/primitives/drawer/drawer-trigger.tsxpackages/headless/src/primitives/drawer/drawer-viewport.tsxpackages/headless/src/primitives/drawer/drawer.test.tsxpackages/headless/src/primitives/drawer/use-drawer-drag.tspackages/headless/src/primitives/file-upload/README.mdpackages/headless/src/primitives/file-upload/file-upload-dropzone.tsxpackages/headless/src/primitives/file-upload/file-upload-item-delete.tsxpackages/headless/src/primitives/file-upload/file-upload-item-preview.tsxpackages/headless/src/primitives/file-upload/file-upload-item.tsxpackages/headless/src/primitives/file-upload/file-upload-root.tsxpackages/headless/src/primitives/file-upload/file-upload-trigger.tsxpackages/headless/src/primitives/file-upload/file-upload.test.tsxpackages/headless/src/primitives/menu/README.mdpackages/headless/src/primitives/menu/menu-arrow.tsxpackages/headless/src/primitives/menu/menu-item.tsxpackages/headless/src/primitives/menu/menu-popup.tsxpackages/headless/src/primitives/menu/menu-positioner.tsxpackages/headless/src/primitives/menu/menu-separator.tsxpackages/headless/src/primitives/menu/menu-trigger.tsxpackages/headless/src/primitives/menu/menu.test.tsxpackages/headless/src/primitives/otp/README.mdpackages/headless/src/primitives/otp/otp-input.tsxpackages/headless/src/primitives/otp/otp-root.tsxpackages/headless/src/primitives/otp/otp.test.tsxpackages/headless/src/primitives/popover/README.mdpackages/headless/src/primitives/popover/popover-arrow.tsxpackages/headless/src/primitives/popover/popover-close.tsxpackages/headless/src/primitives/popover/popover-description.tsxpackages/headless/src/primitives/popover/popover-popup.tsxpackages/headless/src/primitives/popover/popover-positioner.tsxpackages/headless/src/primitives/popover/popover-title.tsxpackages/headless/src/primitives/popover/popover-trigger.tsxpackages/headless/src/primitives/popover/popover.test.tsxpackages/headless/src/primitives/select/README.mdpackages/headless/src/primitives/select/select-arrow.tsxpackages/headless/src/primitives/select/select-option.tsxpackages/headless/src/primitives/select/select-popup.tsxpackages/headless/src/primitives/select/select-positioner.tsxpackages/headless/src/primitives/select/select-trigger.tsxpackages/headless/src/primitives/select/select-value.tsxpackages/headless/src/primitives/select/select.test.tsxpackages/headless/src/primitives/tabs/README.mdpackages/headless/src/primitives/tabs/tabs-indicator.tsxpackages/headless/src/primitives/tabs/tabs-list.tsxpackages/headless/src/primitives/tabs/tabs-panel.tsxpackages/headless/src/primitives/tabs/tabs-tab.tsxpackages/headless/src/primitives/tabs/tabs-trigger.tsxpackages/headless/src/primitives/tabs/tabs.test.tsxpackages/headless/src/primitives/tooltip/README.mdpackages/headless/src/primitives/tooltip/tooltip-arrow.tsxpackages/headless/src/primitives/tooltip/tooltip-popup.tsxpackages/headless/src/primitives/tooltip/tooltip-positioner.tsxpackages/headless/src/primitives/tooltip/tooltip-trigger.tsxpackages/headless/src/primitives/tooltip/tooltip.test.tsxpackages/headless/src/utils/css-vars.tspackages/headless/src/utils/use-render.test.tsxpackages/headless/src/utils/use-render.tsxpackages/swingset/CLAUDE.mdpackages/swingset/src/stories/accordion.mdxpackages/swingset/src/stories/accordion.stories.tsxpackages/swingset/src/stories/autocomplete.mdxpackages/swingset/src/stories/autocomplete.stories.tsxpackages/swingset/src/stories/collapsible.mdxpackages/swingset/src/stories/collapsible.stories.tsxpackages/swingset/src/stories/dialog.component.mdxpackages/swingset/src/stories/dialog.mdxpackages/swingset/src/stories/dialog.stories.tsxpackages/swingset/src/stories/drawer.mdxpackages/swingset/src/stories/drawer.stories.tsxpackages/swingset/src/stories/file-upload.mdxpackages/swingset/src/stories/file-upload.stories.tsxpackages/swingset/src/stories/menu.mdxpackages/swingset/src/stories/menu.stories.tsxpackages/swingset/src/stories/otp.mdxpackages/swingset/src/stories/otp.stories.tsxpackages/swingset/src/stories/popover.mdxpackages/swingset/src/stories/popover.stories.tsxpackages/swingset/src/stories/select.mdxpackages/swingset/src/stories/select.stories.tsxpackages/swingset/src/stories/tabs.component.mdxpackages/swingset/src/stories/tabs.mdxpackages/swingset/src/stories/tabs.stories.tsxpackages/swingset/src/stories/tooltip.mdxpackages/swingset/src/stories/tooltip.stories.tsx
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
clerk/clerk_go(manual)clerk/dashboard(manual)clerk/accounts(manual)clerk/backoffice(manual)clerk/clerk(manual)clerk/clerk-docs(manual)clerk/cloudflare-workers(manual)clerk/cli(auto-detected)clerk/clerk-ios(auto-detected)clerk/clerk-android(auto-detected)
💤 Files with no reviewable changes (13)
- packages/headless/src/primitives/popover/popover-description.tsx
- packages/headless/src/primitives/menu/menu-popup.tsx
- packages/headless/src/primitives/popover/popover-close.tsx
- packages/headless/src/primitives/menu/menu-separator.tsx
- packages/headless/src/primitives/file-upload/file-upload-item-preview.tsx
- packages/headless/src/primitives/select/select-value.tsx
- packages/headless/src/primitives/tooltip/tooltip-popup.tsx
- packages/headless/src/primitives/select/select-popup.tsx
- packages/headless/src/primitives/tabs/tabs-indicator.tsx
- packages/headless/src/primitives/tabs/tabs-list.tsx
- packages/headless/src/primitives/autocomplete/autocomplete-popup.tsx
- packages/headless/src/primitives/popover/popover-title.tsx
- packages/headless/src/primitives/popover/popover-popup.tsx
| onKeyDown: (event: React.KeyboardEvent<HTMLElement>) => { | ||
| if (event.key !== 'Home' && event.key !== 'End') { | ||
| return; | ||
| } | ||
| event.preventDefault(); | ||
| const items = Array.from( | ||
| event.currentTarget.querySelectorAll<HTMLElement>('[data-cl-slot="accordion-trigger"]:not([disabled])'), | ||
| event.currentTarget.querySelectorAll<HTMLElement>('[aria-expanded]:not([disabled])'), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Scope Home/End navigation to this Accordion’s enabled triggers.
[aria-expanded]:not([disabled]) searches the entire subtree, so nested accordions or consumer controls with aria-expanded can be included. It also filters native disabled, while AccordionTrigger represents its disabled state with aria-disabled; disabled triggers may therefore remain in the navigation list. Use the Composite registry or another Accordion-specific selector, and exclude aria-disabled="true".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/headless/src/primitives/accordion/accordion-root.tsx` around lines
60 - 66, Update the Home/End handling in the accordion root’s onKeyDown handler
to collect only this Accordion’s registered or uniquely identified enabled
triggers, excluding elements with aria-disabled="true". Do not use the broad
subtree selector that can include nested accordions or unrelated aria-expanded
controls, and preserve the existing Home/End navigation behavior for the
filtered trigger list.
| .cl-collapsible-panel { | ||
| overflow: hidden; | ||
| height: var(--collapsible-panel-height); | ||
| transition: height 200ms ease; | ||
| } | ||
| [data-cl-slot='collapsible-panel'][data-cl-closed] { | ||
| .cl-collapsible-panel[data-closed] { | ||
| height: 0; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Show the class required by the CSS example.
The new selector targets the consumer-provided .cl-collapsible-panel class, but the usage example never applies it. As written, copying both snippets leaves the panel unmatched and the animation does not run. Add className="cl-collapsible-panel" to the example, or scope the CSS to an attribute emitted by the primitive.
As per coding guidelines, README files must provide working usage examples; this example should demonstrate the class used by its CSS.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/headless/src/primitives/collapsible/README.md` around lines 94 -
100, Update the collapsible usage example to apply
className="cl-collapsible-panel" to the panel element targeted by the CSS
selector, ensuring the documented example works with the provided animation
styles.
Source: Coding guidelines
| data-side={side} | ||
| {...props} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== popover-arrow =="
sed -n '1,120p' packages/headless/src/primitives/popover/popover-arrow.tsx
echo
echo "== select-arrow =="
sed -n '1,120p' packages/headless/src/primitives/select/select-arrow.tsx
echo
echo "== search for mergeProps usage near arrow primitives =="
rg -n "mergeProps|data-side" packages/headless/src/primitives/popover packages/headless/src/primitives/select -g '*.tsx' -g '*.ts'Repository: clerk/javascript
Length of output: 5721
🏁 Script executed:
#!/bin/bash
set -euo pipefail
for f in \
packages/headless/src/primitives/popover/popover-arrow.tsx \
packages/headless/src/primitives/select/select-arrow.tsx
do
echo "===== $f ====="
nl -ba "$f" | sed -n '1,120p'
echo
doneRepository: clerk/javascript
Length of output: 265
Set data-side after consumer props in both arrow components. props currently come last, so callers can override the computed side and break side-based styling.
packages/headless/src/primitives/popover/popover-arrow.tsxpackages/headless/src/primitives/select/select-arrow.tsx
📍 Affects 2 files
packages/headless/src/primitives/popover/popover-arrow.tsx#L19-L20(this comment)packages/headless/src/primitives/select/select-arrow.tsx#L16-L17
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/headless/src/primitives/popover/popover-arrow.tsx` around lines 19 -
20, The computed data-side attribute must take precedence over consumer props in
both arrow components. In
packages/headless/src/primitives/popover/popover-arrow.tsx lines 19-20, move
data-side after the props spread; apply the same ordering change in
packages/headless/src/primitives/select/select-arrow.tsx lines 16-17, preserving
the computed side for styling.
| const ownProps = { | ||
| 'data-cl-slot': 'tooltip-positioner', | ||
| 'data-cl-side': side, | ||
| 'data-side': side, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== tooltip-positioner.tsx ==\n'
cat -n packages/headless/src/primitives/tooltip/tooltip-positioner.tsx
printf '\n== tooltip-arrow.tsx ==\n'
cat -n packages/headless/src/primitives/tooltip/tooltip-arrow.tsxRepository: clerk/javascript
Length of output: 3061
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,120p' packages/headless/src/primitives/tooltip/tooltip-positioner.tsx
printf '\n---\n'
sed -n '1,120p' packages/headless/src/primitives/tooltip/tooltip-arrow.tsxRepository: clerk/javascript
Length of output: 2535
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== mergeProps definition ==\n'
rg -n "export .*mergeProps|function mergeProps|const mergeProps" packages/headless/src -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'
printf '\n== likely utils file ==\n'
fd -a "utils" packages/headless/src | head -n 20Repository: clerk/javascript
Length of output: 804
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,140p' packages/headless/src/utils/use-render.tsxRepository: clerk/javascript
Length of output: 5757
Keep the computed data-side authoritative
Consumer props still override this value in both tooltip surfaces: mergeProps(..., otherProps) lets data-side be replaced in TooltipPositioner, and {...props} after data-side={side} does the same in TooltipArrow. Assign the computed value last, or omit it from consumer overrides.
📍 Affects 2 files
packages/headless/src/primitives/tooltip/tooltip-positioner.tsx#L20-L20(this comment)packages/headless/src/primitives/tooltip/tooltip-arrow.tsx#L19-L19
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/headless/src/primitives/tooltip/tooltip-positioner.tsx` at line 20,
The computed data-side value must remain authoritative in both tooltip surfaces.
Update TooltipPositioner in
packages/headless/src/primitives/tooltip/tooltip-positioner.tsx:20 so mergeProps
does not allow otherProps to override data-side, and update TooltipArrow in
packages/headless/src/primitives/tooltip/tooltip-arrow.tsx:19 so the computed
side is assigned after consumer props; preserve all other prop-merging behavior.
| .cl-accordion-panel { | ||
| overflow: hidden; | ||
| height: var(--cl-accordion-panel-height); | ||
| transition: height 200ms ease; | ||
| } | ||
| [data-cl-slot='accordion-panel'][data-cl-closed] { | ||
| .cl-accordion-panel[data-closed] { |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the CSS examples assign the classes they select.
Both examples now select consumer-owned classes, but neither usage snippet passes those classes to the corresponding primitive. Copying the examples therefore produces no styling.
packages/swingset/src/stories/accordion.mdx#L114-L119: showclassName='cl-accordion-panel'onAccordion.Panel, or use a documented consumer class consistently.packages/swingset/src/stories/tabs.mdx#L122-L122: showclassName='cl-tabs-indicator'onTabs.Indicator, or use a documented consumer class consistently.
📍 Affects 2 files
packages/swingset/src/stories/accordion.mdx#L114-L119(this comment)packages/swingset/src/stories/tabs.mdx#L122-L122
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/swingset/src/stories/accordion.mdx` around lines 114 - 119, Update
the Accordion.Panel usage in packages/swingset/src/stories/accordion.mdx (lines
114-119) to pass the cl-accordion-panel class, and update the Tabs.Indicator
usage in packages/swingset/src/stories/tabs.mdx (line 122) to pass the
cl-tabs-indicator class; keep each example’s CSS selector consistent with the
class assigned to its primitive.
| // Headless primitives ship no styles. This single demo renders the primitive raw — | ||
| // unstyled — so it faithfully reflects what `@clerk/headless` provides: behavior, state, | ||
| // positioning, keyboard navigation, and ARIA wiring via the `data-cl-*` attributes each | ||
| // positioning, keyboard navigation, and ARIA wiring via the `data-*` attributes each |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Describe data-* as state hooks, not ARIA wiring. Roles and aria-* attributes provide the accessibility wiring; these data-* attributes are styling/state selectors.
packages/swingset/src/stories/autocomplete.stories.tsx#L10-L10: replace “ARIA wiring via” with wording that separates ARIA wiring from emitted state attributes.packages/swingset/src/stories/collapsible.stories.tsx#L7-L7: replace “ARIA wiring via” with wording that separates ARIA wiring from emitted state attributes.packages/swingset/src/stories/popover.stories.tsx#L7-L7: replace “ARIA wiring via” with wording that separates ARIA wiring from emitted state attributes.packages/swingset/src/stories/select.stories.tsx#L7-L7: replace “ARIA wiring via” with wording that separates ARIA wiring from emitted state attributes.
📍 Affects 4 files
packages/swingset/src/stories/autocomplete.stories.tsx#L10-L10(this comment)packages/swingset/src/stories/collapsible.stories.tsx#L7-L7packages/swingset/src/stories/popover.stories.tsx#L7-L7packages/swingset/src/stories/select.stories.tsx#L7-L7
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/swingset/src/stories/autocomplete.stories.tsx` at line 10, The story
descriptions incorrectly characterize data-* attributes as ARIA wiring. Update
the wording in the component story descriptions for Autocomplete, Collapsible,
Popover, and Select to describe data-* attributes as emitted state or styling
selectors, while identifying roles and aria-* attributes as the accessibility
wiring; apply this at
packages/swingset/src/stories/autocomplete.stories.tsx:10-10,
packages/swingset/src/stories/collapsible.stories.tsx:7-7,
packages/swingset/src/stories/popover.stories.tsx:7-7, and
packages/swingset/src/stories/select.stories.tsx:7-7.
| `Collapsible.Panel` also exposes `--collapsible-panel-height` / | ||
| `--collapsible-panel-width` (its measured dimensions) for height/width-based | ||
| animations: | ||
|
|
||
| ```css | ||
| [data-cl-slot='collapsible-panel'] { | ||
| .cl-collapsible-panel { | ||
| overflow: hidden; | ||
| height: var(--collapsible-panel-height); | ||
| transition: height 200ms ease; | ||
| } | ||
| [data-cl-slot='collapsible-panel'][data-cl-closed] { | ||
| .cl-collapsible-panel[data-closed] { |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the CSS examples assign their selector classes. Headless parts do not guarantee .cl-collapsible-panel or .cl-popover-popup; the samples currently match nothing unless consumers independently add those classes.
packages/swingset/src/stories/collapsible.mdx#L80-L90: showclassName='cl-collapsible-panel'onCollapsible.Panel, or explicitly state that consumers must assign it.packages/swingset/src/stories/popover.mdx#L121-L127: showclassName='cl-popover-popup'onPopover.Popup, or explicitly state that consumers must assign it.
📍 Affects 2 files
packages/swingset/src/stories/collapsible.mdx#L80-L90(this comment)packages/swingset/src/stories/popover.mdx#L121-L127
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/swingset/src/stories/collapsible.mdx` around lines 80 - 90, Update
the examples so their CSS selectors match the rendered headless parts: in
packages/swingset/src/stories/collapsible.mdx lines 80-90, assign
className='cl-collapsible-panel' to Collapsible.Panel; in
packages/swingset/src/stories/popover.mdx lines 121-127, assign
className='cl-popover-popup' to Popover.Popup. Ensure both samples visibly
demonstrate the required class assignments.
| // Headless primitives ship no styles. This single demo renders the primitive raw — | ||
| // unstyled — so it faithfully reflects what `@clerk/headless` provides: behavior, state, | ||
| // and ARIA wiring via the `data-cl-*` attributes each part emits, with zero appearance. | ||
| // and ARIA wiring via the `data-*` attributes each part emits, with zero appearance. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Separate ARIA wiring from styling attributes.
data-* exposes state/styling hooks; ARIA wiring is provided by aria-* attributes. Reword these comments to describe both independently.
packages/swingset/src/stories/dialog.stories.tsx#L7-L7: say the primitive provides ARIA wiring and emitsdata-*attributes for styling.packages/swingset/src/stories/drawer.stories.tsx#L7-L7: distinguish ARIA wiring from gesture/statedata-*hooks.packages/swingset/src/stories/menu.stories.tsx#L7-L7: distinguish ARIA wiring from positioning and statedata-*hooks.
📍 Affects 3 files
packages/swingset/src/stories/dialog.stories.tsx#L7-L7(this comment)packages/swingset/src/stories/drawer.stories.tsx#L7-L7packages/swingset/src/stories/menu.stories.tsx#L7-L7
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/swingset/src/stories/dialog.stories.tsx` at line 7, Reword the
comments at packages/swingset/src/stories/dialog.stories.tsx#L7-L7 to state that
the primitive provides ARIA wiring and emits data-* attributes for styling; at
packages/swingset/src/stories/drawer.stories.tsx#L7-L7, distinguish ARIA wiring
from gesture/state data-* hooks; and at
packages/swingset/src/stories/menu.stories.tsx#L7-L7, distinguish ARIA wiring
from positioning/state data-* hooks. No implementation changes are needed.
Headless primitives no longer emit
data-cl-slot. Slot identity comes from consumer/Mosaic classNames, not an emitted attr.All primitive state/variant attrs de-prefixed:
data-cl-open→data-open,data-cl-side→data-side, etc. Matches Mosaicdata-<axis>convention. Presence attrs stay split (data-open/data-closed), not Radixdata-state.--cl-*CSS custom properties unchanged (separate namespace).Internal selectors that keyed off slot attrs rewired to stable attrs (
svg[data-side],[aria-expanded], etc). Tests locate bydata-testid/roles instead of slot; pure slot-existence tests deleted.Docs updated: headless READMEs + swingset primitive stories/mdx + swingset house-style. Mosaic layer (
data-cl-sloton styled slots) untouched.Empty changeset:
@clerk/headlessprivate/unpublished, no user-facing published impact.565 tests pass, typecheck + lint clean.